package repository

import (
	"fitness/go-admin/internal/model"

	"gorm.io/gorm"
)

type UserRepository interface {
	Create(user *model.User) error
	Update(user *model.User) error
	Delete(id uint) error
	GetByID(id uint) (*model.User, error)
	GetByUsername(username string) (*model.User, error)
	GetByEmail(email string) (*model.User, error)
	GetByPhone(phone string) (*model.User, error)
	List(page, pageSize int) ([]model.User, int64, error)
	UpdateLastLogin(id uint) error
	GetUserWithRole(id uint) (*model.User, *model.Role, error)
	// 用户管理新增
	GetUserListWithFilter(req *model.UserListReq) ([]*model.UserListItem, int64, error)
	GetUserDetailByID(id uint) (*model.UserDetailResp, error)
	UpdateUserInfo(id uint, req *model.UpdateUserReq) error
	CheckEmailExists(email string, excludeUserID uint) (bool, error)
	CheckPhoneExists(phone string, excludeUserID uint) (bool, error)
	UpdateUserStatus(id uint, status int) error
	UpdateUserRole(id uint, roleID uint) error
}

type userRepository struct {
	db *gorm.DB
}

func NewUserRepository(db *gorm.DB) UserRepository {
	return &userRepository{db: db}
}

func (r *userRepository) Create(user *model.User) error {
	return r.db.Create(user).Error
}

func (r *userRepository) Update(user *model.User) error {
	return r.db.Save(user).Error
}

func (r *userRepository) Delete(id uint) error {
	return r.db.Delete(&model.User{}, id).Error
}

func (r *userRepository) GetByID(id uint) (*model.User, error) {
	var user model.User
	err := r.db.First(&user, id).Error
	return &user, err
}

func (r *userRepository) GetByUsername(username string) (*model.User, error) {
	var user model.User
	err := r.db.Where("username = ?", username).First(&user).Error
	return &user, err
}

func (r *userRepository) GetByEmail(email string) (*model.User, error) {
	var user model.User
	err := r.db.Where("email = ?", email).First(&user).Error
	return &user, err
}

func (r *userRepository) GetByPhone(phone string) (*model.User, error) {
	var user model.User
	err := r.db.Where("phone = ?", phone).First(&user).Error
	return &user, err
}

func (r *userRepository) List(page, pageSize int) ([]model.User, int64, error) {
	var users []model.User
	var total int64

	offset := (page - 1) * pageSize

	if err := r.db.Model(&model.User{}).Count(&total).Error; err != nil {
		return nil, 0, err
	}

	err := r.db.Offset(offset).Limit(pageSize).Order("created_at DESC").Find(&users).Error
	return users, total, err
}

func (r *userRepository) UpdateLastLogin(id uint) error {
	// 使用gorm.Expr("NOW()")确保正确设置时间
	return r.db.Model(&model.User{}).Where("id = ?", id).Update("last_login", gorm.Expr("NOW()")).Error
}

func (r *userRepository) GetUserWithRole(id uint) (*model.User, *model.Role, error) {
	var user model.User
	var role model.Role

	if err := r.db.First(&user, id).Error; err != nil {
		return nil, nil, err
	}

	if err := r.db.First(&role, user.RoleID).Error; err != nil {
		return &user, nil, err
	}

	return &user, &role, nil
}

// GetUserListWithFilter 获取用户列表(支持筛选)
func (r *userRepository) GetUserListWithFilter(req *model.UserListReq) ([]*model.UserListItem, int64, error) {
	var total int64
	var users []*model.UserListItem

	// 构建查询
	query := r.db.Table("users").
		Select("users.id, users.username, users.email, users.phone, users.nickname, users.avatar, users.role_id, roles.name as role_name, users.status, users.last_login, users.created_at").
		Joins("LEFT JOIN roles ON users.role_id = roles.id")

	// 角色筛选
	if req.Role != "" {
		query = query.Where("roles.code = ?", req.Role)
	}

	// 状态筛选
	if req.Status != nil {
		query = query.Where("users.status = ?", *req.Status)
	}

	// 关键词搜索 (用户名/邮箱/手机号)
	if req.Keyword != "" {
		keyword := "%" + req.Keyword + "%"
		query = query.Where("users.username LIKE ? OR users.email LIKE ? OR users.phone LIKE ?", keyword, keyword, keyword)
	}

	// 统计总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 分页查询
	offset := (req.Page - 1) * req.PageSize
	err := query.Offset(offset).Limit(req.PageSize).Order("users.created_at DESC").Scan(&users).Error

	return users, total, err
}

// GetUserDetailByID 获取用户详情(包含角色信息)
func (r *userRepository) GetUserDetailByID(id uint) (*model.UserDetailResp, error) {
	var detail model.UserDetailResp

	err := r.db.Table("users").
		Select("users.id, users.username, users.email, users.phone, users.nickname, users.avatar, users.role_id, roles.name as role_name, users.status, users.last_login, users.created_at, users.updated_at").
		Joins("LEFT JOIN roles ON users.role_id = roles.id").
		Where("users.id = ?", id).
		Scan(&detail).Error

	if err != nil {
		return nil, err
	}

	// 检查是否找到用户
	if detail.ID == 0 {
		return nil, gorm.ErrRecordNotFound
	}

	return &detail, nil
}

// UpdateUserInfo 更新用户信息
func (r *userRepository) UpdateUserInfo(id uint, req *model.UpdateUserReq) error {
	updates := make(map[string]interface{})

	if req.Nickname != "" {
		updates["nickname"] = req.Nickname
	}
	if req.Email != "" {
		updates["email"] = req.Email
	}
	if req.Phone != "" {
		updates["phone"] = req.Phone
	}

	if len(updates) == 0 {
		return nil
	}

	return r.db.Model(&model.User{}).Where("id = ?", id).Updates(updates).Error
}

// CheckEmailExists 检查邮箱是否已存在(排除指定用户ID)
func (r *userRepository) CheckEmailExists(email string, excludeUserID uint) (bool, error) {
	var count int64
	query := r.db.Model(&model.User{}).Where("email = ?", email)
	if excludeUserID > 0 {
		query = query.Where("id != ?", excludeUserID)
	}
	err := query.Count(&count).Error
	return count > 0, err
}

// CheckPhoneExists 检查手机号是否已存在(排除指定用户ID)
func (r *userRepository) CheckPhoneExists(phone string, excludeUserID uint) (bool, error) {
	var count int64
	query := r.db.Model(&model.User{}).Where("phone = ?", phone)
	if excludeUserID > 0 {
		query = query.Where("id != ?", excludeUserID)
	}
	err := query.Count(&count).Error
	return count > 0, err
}

// UpdateUserStatus 更新用户状态
func (r *userRepository) UpdateUserStatus(id uint, status int) error {
	return r.db.Model(&model.User{}).Where("id = ?", id).Update("status", status).Error
}

// UpdateUserRole 更新用户角色
func (r *userRepository) UpdateUserRole(id uint, roleID uint) error {
	return r.db.Model(&model.User{}).Where("id = ?", id).Update("role_id", roleID).Error
}
